#ifndef GAMEENGINE_GRAPHICS_MESHES_TRGL_MESH_H
#define GAMEENGINE_GRAPHICS_MESHES_TRGL_MESH_H

#include <GameEngine/Graphics/graphics_settings.h>

#include <GameEngine/Graphics/Meshes/surface_mesh.h>
#include <GameEngine/Graphics/Meshes/trgl_mesh_group.h>
#include <GameEngine/Graphics/Texture/texture_coordinates.h>
#include <GameEngine/Geometry/Location/point3d.h>
#include <GameEngine/Geometry/Location/vector3d.h>

#include <vector>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

class TrglMeshCreator;
class TrglMeshIO;

//=================================================================================

//! Mesh made of a set of triangles
/*!
 *  This class implements a surface mesh made of a set of triangles. The mesh format handles a list
 *  of vertices (plus optionally, a list of normals and a list of texture coordinates); the triangles
 *  actually consist in a triplet of vertex indexes (plus optionally, indexes to the normals and texture
 *  coordinates) rather than a triplet of vertices. This format allows to avoid data redundancy, since
 *  most of the vertices are shared between different triangles.
 *
 *  The triangles of the mesh are divided into groups of triangles, which typically correspond to one
 *  identifyable surface of the object (for example, the blade of a sword). Triangle groups are further
 *  divided into subgroups, which correspond to triangles using the same king of material (for example,
 *  most of the blade will typically reflect most of the incident light, except for the sharpened edge
 *  that is usually much less shiny).
 *
 *  Triangle meshes can be built in two ways: they can either be loaded from a file using the TrglMeshIO
 *  class, or created "manually" triangle by triangle using the TrglMeshCreator class. Both classes aim
 *  at maintaining the consistency of the mesh.
 *
 *  The triangle mesh class can handle safely a mixture of triangles with and without normals and / or
 *  texture coordinates. All file formats do not allow this level of flexibility, however - for instance,
 *  NetImmerse files require all triangles in a group to be either with or without normals / texture
 *  coordinates. In general, when saving to such file formats, it is recommended that the mesh homogeneously
 *  either uses or does not use normals and / or texture coordinates. Results with non-complying meshes
 *  are unpredictable, and can range from no issue (GameEngine most often tries to guess missing data,
 *  which can sometimes save the day) to corrupted files or application crashes.
 */
class _Graphics_decl TrglMesh : public SurfaceMesh {
	//! The TrglMeshCreator needs to access the mesh to modify directly its data
	friend class TrglMeshCreator;
	//! The TrglMeshSubGroup needs to access the mesh to read its vertices, texture coordinates and normals for the rendering
	friend class TrglMeshSubGroup;
	//! The TrglMeshIO needs to access the mesh to modify directly its data
	friend class TrglMeshIO;

public:
	TrglMesh();
	virtual ~TrglMesh();

	virtual bool render_mesh(const Line3d<float>& ray, bool transparency);

	void merge(const TrglMesh& rhs);

	bool load_obj_file(const GEString& file, float scale = 1.0f);
	bool save_obj_file(const GEString& file) const;
	bool load_bin_file(const GEString& file, float scale = 1.0f);
	bool save_bin_file(const GEString& file) const;
	bool load_nif_file(const GEString& file, float scale = 1.0f);
	bool save_nif_file(const GEString& file) const;
	bool load_3ds_file(const GEString& file, float scale = 1.0f);
	bool save_3ds_file(const GEString& file) const;

	virtual VertexCount vertex_count() const;
	virtual NormalCount normal_count() const;
	virtual TextureCoordinateCount texture_coordinate_count() const;
	virtual FaceCount face_count() const;

protected:
	void add_subgroup(const TrglMeshSubGroup& subgroup, const GEString group_name = "Default");

protected:
	//! The list of vertices associated to the mesh
	GAMEENGINE_DLL_CLASS_STD(vector,Point3d<float>) vertices_;
	//! The list of normals associated to the mesh
	GAMEENGINE_DLL_CLASS_STD(vector,Vector3d<float>) normals_;
	//! The list of texture coordinates associated to the mesh
	GAMEENGINE_DLL_CLASS_STD(vector,TextureCoordinate2d) coords_;

	//! The triangle groups present in the mesh
	GAMEENGINE_DLL_CLASS_STD(vector,TrglMeshGroup) trgl_groups_;
};

//=================================================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
